Popular Searches
Popular Course Categories
Popular Courses

Understanding Bean Scopes and Lifecycle

Understanding Bean Scopes and Lifecycle

Spring Framework and Dependency Injection

Understanding Bean Scopes and Lifecycle in Spring Framework

Course: Advance Java Training

Topic: Understanding Bean Scopes and Lifecycle

Course Link: Advance Java Training Course

Demo Link: Register for a Free Course Demo

JustAcademy Website: Visit JustAcademy


1. Introduction to Spring Beans

In the Spring Framework, a bean is an object that is created, configured, and managed by the Spring IoC (Inversion of Control) container. Instead of creating and managing every application object manually, developers can allow Spring to handle object creation, dependency injection, initialization, and destruction.

Bean scopes define how many instances of a bean Spring creates and how long those instances are associated with a particular context. The bean lifecycle describes the stages a bean passes through, from creation to eventual destruction.

Understanding scopes and lifecycle is important when building scalable, maintainable, and reliable Java applications.

Example of a Spring Bean

import org.springframework.stereotype.Component;

@Component
public class NotificationService {
    public void sendNotification() {
        System.out.println("Notification sent successfully.");
    }
}

The @Component annotation tells Spring that this class can be detected during component scanning and registered as a bean. Spring then manages the bean according to its configured scope and lifecycle.

2. Learning Objectives

  • Understand Spring beans and the role of the IoC container.
  • Learn the major Spring bean scopes.
  • Understand singleton and prototype scope differences.
  • Explore request, session, application, and WebSocket scopes.
  • Understand the complete Spring bean lifecycle.
  • Use initialization and destruction callbacks.
  • Learn lifecycle annotations such as @PostConstruct and @PreDestroy.
  • Configure bean scopes using annotations and Java configuration.
  • Identify common scope and lifecycle problems.

3. What Is Bean Scope?

Bean scope determines the lifecycle and visibility of a bean instance managed by Spring. It controls whether Spring reuses a single instance or creates separate instances for different requests, sessions, or retrieval operations.

For example, a shared service that contains no user-specific mutable state is often suitable for singleton scope. A temporary object that should be created each time it is requested may be suitable for prototype scope.

Why Bean Scope Matters

  • Memory management: Controls how objects are created and retained.
  • State management: Helps isolate data that belongs to individual users or requests.
  • Performance: Avoids unnecessary object creation when reuse is appropriate.
  • Thread safety: Helps developers choose the correct sharing model for mutable objects.
  • Application design: Supports separation between shared services and user-specific components.

4. Types of Bean Scopes in Spring

Spring provides several bean scopes. The core scopes available in a standard Spring application include singleton and prototype. Web-aware application contexts additionally support request, session, application, and WebSocket scopes.

Scope Instance Behavior Typical Use Case
Singleton One bean instance per Spring IoC container and bean definition. Shared services, repositories, configuration components.
Prototype A new instance is created whenever Spring resolves the bean from the container. Short-lived objects that need separate state.
Request One instance per HTTP request. Request-specific data and processing.
Session One instance per HTTP session. User-session-specific state.
Application One instance per ServletContext in a web application. Shared web-application-level state.
WebSocket One instance per WebSocket session. State associated with a WebSocket connection.

Important: Request, session, application, and WebSocket scopes require a suitable web-aware Spring environment. They are not available in every standalone Spring application by default.

5. Singleton Scope

Singleton is the default Spring bean scope. Spring creates one instance for a given bean definition in a particular IoC container and returns that shared instance when the bean is requested again from that container.

Example

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

@Component
@Scope("singleton")
public class ReportService {
    public void generateReport() {
        System.out.println("Generating report...");
    }
}

Because singleton is the default, the explicit @Scope("singleton") annotation is optional in this example.

Checking Singleton Behavior

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class SingletonExample {
    public static void main(String[] args) {
        ApplicationContext context =
            new AnnotationConfigApplicationContext(AppConfig.class);

        ReportService first = context.getBean(ReportService.class);
        ReportService second = context.getBean(ReportService.class);

        System.out.println(first == second); // true
    }
}

The expression first == second evaluates to true because both references point to the same managed bean instance.

Advantages of Singleton Scope

  • Reduces repeated object creation.
  • Allows multiple components to reuse a shared service.
  • Works well for stateless services and repositories.
  • Fits many standard service-layer components in Spring applications.

Limitations and Precautions

  • Mutable instance fields may be shared by concurrent requests.
  • Developers must avoid storing request-specific information in shared fields.
  • Singleton scope does not automatically make a bean thread-safe.
  • It means one instance per container and bean definition, not one instance for the entire JVM.

6. Prototype Scope

With prototype scope, Spring creates a new bean instance whenever the container is asked to resolve that bean. This is useful when separate consumers need independent object state.

Example

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

@Component
@Scope("prototype")
public class ShoppingCartDraft {
    private int itemCount;

    public void addItem() {
        itemCount++;
    }

    public int getItemCount() {
        return itemCount;
    }
}

Testing Prototype Behavior

ShoppingCartDraft first =
    context.getBean(ShoppingCartDraft.class);

ShoppingCartDraft second =
    context.getBean(ShoppingCartDraft.class);

System.out.println(first == second); // false

Each container lookup creates a distinct prototype instance, so the comparison returns false.

Important Prototype Lifecycle Detail

Spring manages prototype bean creation, dependency injection, and initialization callbacks. After returning the fully initialized prototype bean, Spring generally does not manage its complete destruction lifecycle. If a prototype bean owns resources that must be released, the application should arrange cleanup explicitly.

Singleton vs Prototype

Feature Singleton Prototype
Instance creation One instance per bean definition and container. New instance for each container resolution.
Default scope Yes No
Object reuse Shared Not shared across separate lookups by default
Typical use Stateless services Independent stateful objects
Destruction callback Normally invoked when the container closes. Not automatically managed after handoff in the usual way.

7. Request Scope

Request scope creates one bean instance for each HTTP request. Components participating in the same request can share that request-scoped instance, while a later HTTP request receives another instance.

Example

import org.springframework.stereotype.Component;
import org.springframework.web.context.annotation.RequestScope;

@Component
@RequestScope
public class RequestDetails {
    private String requestId;

    public String getRequestId() {
        return requestId;
    }

    public void setRequestId(String requestId) {
        this.requestId = requestId;
    }
}

This bean can hold data associated with the current request, such as a correlation identifier. In production applications, ensure request-specific values are initialized correctly and avoid exposing sensitive information.

Common Uses

  • Request correlation identifiers.
  • Temporary request-processing metadata.
  • Request-specific view or workflow data.

8. Session Scope

Session scope creates a bean instance for each HTTP session. Requests associated with the same session use that session's bean instance, subject to the web application's lifecycle and configuration.

Example

import org.springframework.stereotype.Component;
import org.springframework.web.context.annotation.SessionScope;

@Component
@SessionScope
public class UserSessionPreferences {
    private String theme = "light";

    public String getTheme() {
        return theme;
    }

    public void setTheme(String theme) {
        this.theme = theme;
    }
}

Typical Uses

  • Temporary user interface preferences.
  • Multi-step workflow information.
  • Session-specific application state.

Security note: Avoid placing passwords, access tokens, payment details, or other highly sensitive data in session-scoped objects without a carefully designed security approach. Session state should also be kept small and managed with appropriate expiration and invalidation policies.

9. Application Scope

Application scope maintains one bean instance per ServletContext in a web application. It is useful for state intended to be shared across sessions within that web application.

Example

import org.springframework.stereotype.Component;
import org.springframework.web.context.annotation.ApplicationScope;

@Component
@ApplicationScope
public class ApplicationStatistics {
    private long processedRequests;

    public long getProcessedRequests() {
        return processedRequests;
    }

    public synchronized void incrementProcessedRequests() {
        processedRequests++;
    }
}

This simplified counter demonstrates shared application-level state. Real production metrics are usually better handled by a dedicated monitoring or metrics system, especially in applications running across multiple server instances.

Important Considerations

  • Application-scoped state can be shared by concurrent requests.
  • Mutable fields require an appropriate concurrency strategy.
  • In a distributed deployment, each application instance may have its own ServletContext and its own in-memory state.

10. WebSocket Scope

WebSocket scope associates a bean instance with a WebSocket session. It can be useful when maintaining state for a persistent, bidirectional connection between a client and server.

Potential Use Cases

  • Connection-specific communication state.
  • Per-session collaboration metadata.
  • Temporary state for live dashboards or chat connections.

WebSocket-scoped beans require WebSocket support and the appropriate Spring configuration. Their lifetime is tied to the WebSocket session rather than to an ordinary HTTP request.

11. Configuring Bean Scope with Java Configuration

Spring supports Java-based configuration using @Configuration and @Bean. You can specify a scope with the scope attribute of @Bean.

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;

@Configuration
public class AppConfig {

    @Bean
    @Scope("singleton")
    public ReportService reportService() {
        return new ReportService();
    }

    @Bean
    @Scope("prototype")
    public ShoppingCartDraft shoppingCartDraft() {
        return new ShoppingCartDraft();
    }
}

Use Java configuration when you want explicit control over bean creation or when registering classes that do not use component-scanning annotations.

12. What Is the Spring Bean Lifecycle?

The Spring bean lifecycle describes the sequence of steps through which a bean passes while managed by the Spring container. The exact sequence can vary depending on how the bean is defined and which lifecycle interfaces, annotations, or post-processors are used.

A simplified lifecycle is:

  1. The container reads configuration and identifies bean definitions.
  2. Spring instantiates the bean.
  3. Spring injects dependencies and applies property values.
  4. Aware callbacks may run when applicable.
  5. Bean post-processors can process the bean before initialization.
  6. Initialization callbacks execute.
  7. Bean post-processors can process the bean after initialization, potentially returning a proxy.
  8. The bean is ready for use.
  9. When the relevant container or scope ends, applicable destruction callbacks run.

Lifecycle Flow

Bean Definition
      |
      v
Instantiation
      |
      v
Dependency Injection
      |
      v
Aware Callbacks (if applicable)
      |
      v
Before-Initialization Processing
      |
      v
Initialization Callbacks
      |
      v
After-Initialization Processing
      |
      v
Bean Ready for Use
      |
      v
Destruction Callbacks (when managed lifecycle ends)

Bean post-processors may modify a bean or wrap it in a proxy. This is one way Spring implements features such as declarative transactions and certain forms of method interception.

```html

13. Initialization Callbacks in Spring

Initialization callbacks allow a bean to perform setup tasks after Spring has instantiated it and injected its dependencies. These callbacks are useful for validating configuration, preparing internal resources, or loading required application data.

13.1 Using @PostConstruct

The @PostConstruct annotation marks a method that should run after dependency injection and before the bean is used normally. In modern Spring applications, import it from jakarta.annotation.PostConstruct when using compatible Jakarta-based dependencies.

import jakarta.annotation.PostConstruct;
import org.springframework.stereotype.Component;

@Component
public class DatabaseService {

    @PostConstruct
    public void initialize() {
        System.out.println("DatabaseService initialized.");
    }

    public void connect() {
        System.out.println("Database operation started.");
    }
}

Spring invokes the annotated initialization method as part of the bean initialization process. The method should not depend on application requests already being available.

13.2 Implementing InitializingBean

A bean can implement the InitializingBean interface and override its afterPropertiesSet() method.

import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;

@Component
public class CacheService implements InitializingBean {

    @Override
    public void afterPropertiesSet() {
        System.out.println("CacheService initialized.");
    }
}

This approach works, but it couples the class directly to a Spring interface. Annotation-based callbacks or configuration-based initialization methods may be preferable when you want less framework coupling.

13.3 Using initMethod in Java Configuration

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AppConfig {

    @Bean(initMethod = "initialize")
    public FileProcessingService fileProcessingService() {
        return new FileProcessingService();
    }
}

class FileProcessingService {

    public void initialize() {
        System.out.println("Preparing file processing resources.");
    }
}

The initMethod attribute identifies the method Spring should invoke during initialization.

14. Destruction Callbacks in Spring

Destruction callbacks allow Spring-managed beans to release resources when their managed lifecycle ends. These methods may close connections, stop background tasks, release file handles, or perform other cleanup operations.

14.1 Using @PreDestroy

import jakarta.annotation.PreDestroy;
import jakarta.annotation.PostConstruct;
import org.springframework.stereotype.Component;

@Component
public class FileService {

    @PostConstruct
    public void initialize() {
        System.out.println("FileService started.");
    }

    @PreDestroy
    public void cleanup() {
        System.out.println("Releasing FileService resources.");
    }
}

The @PreDestroy method is invoked when Spring performs destruction of the managed bean, provided the applicable scope and container shutdown process support that callback.

14.2 Implementing DisposableBean

import org.springframework.beans.factory.DisposableBean;
import org.springframework.stereotype.Component;

@Component
public class ConnectionManager implements DisposableBean {

    @Override
    public void destroy() {
        System.out.println("Cleaning up connection resources.");
    }
}

Spring calls destroy() when it destroys the managed bean. Implementing this interface directly couples the class to Spring.

14.3 Using destroyMethod

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ResourceConfig {

    @Bean(destroyMethod = "close")
    public ResourceHandler resourceHandler() {
        return new ResourceHandler();
    }
}

class ResourceHandler {

    public void close() {
        System.out.println("ResourceHandler closed.");
    }
}

This configuration tells Spring to call close() when the managed bean is destroyed. Ensure the configured method exists and that the resource is genuinely owned by the bean.

15. Complete Bean Lifecycle Example

The following example demonstrates constructor execution, dependency injection, initialization, normal method execution, and destruction when the Spring context is closed.

import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

class MessageService {

    public MessageService() {
        System.out.println("1. Constructor called");
    }

    @PostConstruct
    public void initialize() {
        System.out.println("2. Initialization completed");
    }

    public void sendMessage() {
        System.out.println("3. Message sent");
    }

    @PreDestroy
    public void cleanup() {
        System.out.println("4. Cleanup executed");
    }
}

@Configuration
class LifecycleConfig {

    @Bean
    public MessageService messageService() {
        return new MessageService();
    }
}

public class LifecycleDemo {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context =
            new AnnotationConfigApplicationContext(LifecycleConfig.class);

        MessageService service =
            context.getBean(MessageService.class);

        service.sendMessage();

        context.close();
    }
}

Expected Output

1. Constructor called
2. Initialization completed
3. Message sent
4. Cleanup executed

The exact lifecycle can involve additional callbacks and bean post-processors. This example illustrates the main stages without showing every internal Spring operation.

16. Lifecycle Interfaces and Annotations

Mechanism Purpose Typical Method or Annotation
Initialization annotation Run setup logic after dependency injection. @PostConstruct
Destruction annotation Run cleanup logic when the managed lifecycle ends. @PreDestroy
Initialization interface Provide an initialization callback. InitializingBean.afterPropertiesSet()
Destruction interface Provide a destruction callback. DisposableBean.destroy()
Java configuration Specify custom lifecycle methods. @Bean(initMethod, destroyMethod)
XML configuration Configure lifecycle callbacks in bean definitions. init-method, destroy-method
Bean post-processor Customize bean instances before or after initialization. BeanPostProcessor

17. BeanPostProcessor and BeanFactoryPostProcessor

Spring offers extension points that let developers customize how beans are processed.

17.1 BeanPostProcessor

A BeanPostProcessor operates on bean instances. It can run logic before and after initialization callbacks. Spring uses post-processors internally for many framework features, including some annotation processing and proxy-related behavior.

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;

@Component
public class LoggingBeanPostProcessor
        implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(
            Object bean, String beanName) throws BeansException {
        System.out.println("Before initialization: " + beanName);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(
            Object bean, String beanName) throws BeansException {
        System.out.println("After initialization: " + beanName);
        return bean;
    }
}

This example logs lifecycle processing for beans handled by the post-processor. In a real application, avoid excessive logging or expensive work in these methods because they can run for many beans during container startup.

17.2 BeanFactoryPostProcessor

A BeanFactoryPostProcessor works with bean definition metadata before regular bean instances are created. It is useful when modifying configuration metadata rather than changing the behavior of an already-instantiated bean.

Feature BeanPostProcessor BeanFactoryPostProcessor
Main target Bean instances Bean definitions and metadata
Timing Around bean initialization Before ordinary bean instantiation is completed
Typical purpose Inspect, modify, or wrap bean instances Customize configuration metadata

18. Dependency Injection and Bean Scope Interaction

Bean scopes become especially important when one bean depends on another bean with a different scope.

Example: Injecting a Prototype Bean into a Singleton

@Component
@Scope("prototype")
class TaskContext {
}

@Component
class TaskService {

    private final TaskContext taskContext;

    public TaskService(TaskContext taskContext) {
        this.taskContext = taskContext;
    }

    public TaskContext getTaskContext() {
        return taskContext;
    }
}

In this example, Spring normally resolves the prototype dependency when it creates the singleton TaskService. The singleton then retains that same injected TaskContext reference. It does not automatically receive a new prototype instance every time a service method is called.

Obtaining a Fresh Prototype Instance on Demand

When a singleton needs a new prototype bean repeatedly, use ObjectProvider to request an instance when needed.

import org.springframework.beans.factory.ObjectProvider;
import org.springframework.stereotype.Component;

@Component
class TaskService {

    private final ObjectProvider<TaskContext> taskContextProvider;

    public TaskService(
            ObjectProvider<TaskContext> taskContextProvider) {
        this.taskContextProvider = taskContextProvider;
    }

    public void executeTask() {
        TaskContext context = taskContextProvider.getObject();
        System.out.println("Using a fresh task context.");
    }
}

Because TaskContext has prototype scope, calling getObject() resolves a new instance each time in the usual configuration. This approach is useful when a shorter-lived bean must be acquired by a longer-lived component.

Injecting Web-Scoped Beans into Longer-Lived Beans

A singleton that depends on a request- or session-scoped bean needs special care. Directly retaining a specific short-lived object can lead to incorrect behavior. Spring scoped proxies or provider-based access can allow the correct scoped instance to be resolved when needed.

19. Lazy Initialization and Bean Scope

By default, singleton beans are generally created during application-context startup unless lazy initialization or other configuration changes that behavior. Lazy initialization delays creation until the bean is first needed.

import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

@Component
@Lazy
public class HeavyReportService {

    public HeavyReportService() {
        System.out.println("HeavyReportService created.");
    }
}

Lazy initialization can reduce startup work, but it may delay the discovery of configuration problems until the bean is first requested. It does not change the bean's scope: a lazy singleton is still a singleton.

20. Common Bean Scope and Lifecycle Errors

Problem Cause Solution
Unexpected shared data Mutable state stored in a singleton bean. Prefer stateless services or isolate state in an appropriate scope.
Prototype object is reused A prototype bean is injected once into a singleton. Use ObjectProvider or another suitable lookup strategy.
Destruction callback does not run Prototype beans are not fully lifecycle-managed after being handed to the caller. Arrange explicit cleanup for prototype-owned resources.
Unknown web scope error A web scope is used in a non-web-aware application context. Use a web-aware context and appropriate web configuration.
Initialization method fails Invalid configuration, missing dependencies, or an exception during setup. Validate dependencies and inspect startup logs.
Cleanup is skipped The context is not closed cleanly or the bean is outside Spring's managed lifecycle. Close the context correctly and verify bean registration and scope.
Request-scoped bean used outside a request No active request context is available. Access it within a valid request or use an appropriate proxy/provider design.

21. Best Practices for Bean Scopes and Lifecycle

  • Use singleton scope for stateless services, repositories, and reusable components in most applications.
  • Avoid storing request-specific or user-specific mutable data in singleton fields.
  • Use prototype scope only when independently created objects are genuinely required.
  • Use request and session scopes only when their web lifecycle matches the data being managed.
  • Use @PostConstruct for lightweight initialization that depends on injected properties.
  • Use @PreDestroy or configured destruction methods to release resources owned by managed beans.
  • Prefer annotation-based lifecycle callbacks or configuration methods over Spring-specific lifecycle interfaces when reducing framework coupling is important.
  • Do not assume that a prototype bean's destruction callback will be called automatically.
  • Use ObjectProvider or scoped proxies when a bean needs access to shorter-lived dependencies.
  • Keep initialization and destruction methods predictable, fast, and easy to test.
  • Make shared mutable state thread-safe when concurrent access is possible.
  • Test lifecycle behavior by creating and closing an application context in a controlled test.

22. Practical Exercise

Exercise: Build a Spring Bean Lifecycle Demonstration

Create a small Spring application with the following requirements:

  1. Create a NotificationService class registered as a Spring bean.
  2. Configure one singleton bean and one prototype bean.
  3. Add an initialization callback that logs when the bean is ready.
  4. Add a destruction callback that logs when the managed lifecycle ends.
  5. Retrieve the singleton bean twice and compare the references.
  6. Retrieve the prototype bean twice and compare the references.
  7. Close the Spring application context and observe the destruction callback.
  8. Explain why the prototype bean's destruction callback is not automatically managed in the same way.

Expected Learning Outcome

After completing this exercise, you should be able to explain instance reuse, initialization order, destruction behavior, and the relationship between bean scope and lifecycle management.

23. Mini Project: Resource Management Service

Develop a small resource management application using Spring. The application should demonstrate how beans are created, initialized, reused, and cleaned up.

Project Requirements

  • Create a singleton ResourceManager service.
  • Create a prototype ResourceTask object for independent task state.
  • Use ObjectProvider<ResourceTask> to create task instances on demand.
  • Initialize shared resources in an appropriate lifecycle callback.
  • Release managed resources during destruction.
  • Write tests verifying singleton reuse and prototype instance separation.
  • Document the limitations of prototype destruction callbacks.

Testing Checklist

  • Does Spring create one singleton instance per bean definition and container?
  • Does each prototype lookup return a distinct object?
  • Does the initialization callback execute at the expected stage?
  • Does the destruction callback execute when the managed singleton is destroyed?
  • Are resources owned by prototype instances cleaned up explicitly?

24. Interview Questions and Answers

Q1. What is a Spring bean?

A Spring bean is an object created, configured, and managed by the Spring IoC container.

Q2. What is bean scope?

Bean scope defines how Spring creates and associates bean instances with a particular context or lifecycle.

Q3. What is the default bean scope?

Singleton is the default scope. It provides one instance per bean definition within a Spring IoC container.

Q4. How does singleton scope differ from the Singleton design pattern?

Spring singleton scope is managed per container and bean definition. The classic Singleton design pattern typically restricts a class to one instance within a particular class-loading context through class-level implementation.

Q5. What is prototype scope?

Prototype scope creates a new instance whenever the container resolves the bean definition.

Q6. Does Spring destroy prototype beans automatically?

Spring initializes prototype beans but generally does not manage their destruction callbacks after handing them to the caller. The application must arrange cleanup for resources owned by such objects.

Q7. What does @PostConstruct do?

It marks a method to run during bean initialization after dependency injection and before the bean is used normally.

Q8. What does @PreDestroy do?

It marks a cleanup method that Spring invokes when the bean's managed lifecycle is being destroyed, where supported.

Q9. What is the purpose of BeanPostProcessor?

It allows Spring or application code to process bean instances before and after initialization callbacks.

Q10. What is the purpose of BeanFactoryPostProcessor?

It allows customization of bean definition metadata before regular bean instantiation is completed.

Q11. What is request scope?

Request scope creates a bean instance for each HTTP request in a web-aware Spring application context.

Q12. What is session scope?

Session scope associates a bean instance with an HTTP session.

Q13. What happens when a prototype bean is injected into a singleton?

The prototype dependency is normally resolved once when the singleton is created. The singleton retains that reference unless it explicitly requests another instance.

Q14. How can a singleton obtain a fresh prototype bean for each operation?

It can use ObjectProvider<T> and call getObject() whenever a new prototype instance is needed.

Q15. Why should singleton services usually be stateless?

Singleton instances are shared, potentially across concurrent requests. Avoiding request-specific mutable state reduces data leakage and concurrency risks.

25. Quick Revision Checklist

  • Bean: An object managed by Spring.
  • Scope: Determines instance creation and contextual lifetime.
  • Singleton: One instance per bean definition and container.
  • Prototype: New instance for each container resolution.
  • Request: One instance per HTTP request.
  • Session: One instance per HTTP session.
  • Application: One instance per ServletContext.
  • WebSocket: One instance per WebSocket session.
  • @PostConstruct: Initialization callback.
  • @PreDestroy: Destruction callback.
  • InitializingBean: Provides afterPropertiesSet().
  • DisposableBean: Provides destroy().
  • BeanPostProcessor: Processes bean instances around initialization.
  • BeanFactoryPostProcessor: Customizes bean definition metadata.
  • ObjectProvider: Supports on-demand dependency resolution.

26. Conclusion

Understanding bean scopes and lifecycle is essential for developing robust Spring applications. Scopes determine how instances are created and shared, while lifecycle callbacks provide controlled points for initialization and cleanup. Singleton beans are suitable for many stateless services, whereas prototype and web scopes serve situations where separate state or a specific contextual lifetime is required.

By selecting the right scope, handling mutable state carefully, and managing resources through appropriate lifecycle callbacks, developers can build Spring applications that are easier to maintain, test, and scale.

Learn More with JustAcademy

Explore the Advance Java Training Course to continue learning Spring Framework concepts and Java application development.

Register for a Course Demo to learn more about the training program.

Visit the JustAcademy website to explore additional courses and learning resources.

Previous Next
whatsapp